/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.querydsl;

import com.querydsl.core.types.Expression;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;

import java.io.Serializable;
import java.util.List;

/**
 * @param <E>
 * @param <ID>
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 */
public interface Dao<E, ID extends Serializable> {

    /**
     * 创建一个select执行器
     *
     * @return
     */
    SelectExecuter<E, ID> select();

    SelectExecuter<E, ID> select(Path<?>... columns);

    SelectExecuter<E, ID> selectExclude(Path<?>... columns);

    List<E> find(BooleanExpression condition, OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, Paging paging, OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, IncludeColumns includeColumns, OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, IncludeColumns includeColumns, Paging paging,
                   OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, IncludeColumns includeColumns, GroupBy groupBy,
                   OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, IncludeColumns includeColumns, GroupBy groupBy,
                   Paging paging, OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, ExcludeColumns excludeColumns, OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, ExcludeColumns excludeColumns, Paging paging,
                   OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, ExcludeColumns excludeColumns, GroupBy groupBy,
                   OrderSpecifier<?>... orders);

    List<E> find(BooleanExpression condition, ExcludeColumns excludeColumns, GroupBy groupBy,
                   Paging paging, OrderSpecifier<?>... orders);

    List<E> findAll(OrderSpecifier<?>... orders);

    List<E> findAll(Paging paging, OrderSpecifier<?>... orders);

    List<E> findAll(IncludeColumns includeColumns, OrderSpecifier<?>... orders);

    List<E> findAll(IncludeColumns includeColumns, Paging paging, OrderSpecifier<?>... orders);

    List<E> findAll(ExcludeColumns excludeColumns, OrderSpecifier<?>... orders);

    List<E> findAll(ExcludeColumns excludeColumns, Paging paging, OrderSpecifier<?>... orders);

    E findByPk(ID pk);

    E findByPk(ID pk, IncludeColumns includeColumns);

    E findByPk(ID pk, ExcludeColumns excludeColumns);

    E findOne(BooleanExpression condition);

    E findOne(BooleanExpression condition, IncludeColumns includeColumns);

    E findOne(BooleanExpression condition, IncludeColumns includeColumns, GroupBy groupBy);

    E findOne(BooleanExpression condition, ExcludeColumns excludeColumns);

    E findOne(BooleanExpression condition, ExcludeColumns excludeColumns, GroupBy groupBy);

    E findFirst(BooleanExpression condition, OrderSpecifier<?>... orders);

    E findFirst(BooleanExpression condition, GroupBy groupBy, OrderSpecifier<?>... orders);

    E findFirst(BooleanExpression condition, IncludeColumns includeColumns, OrderSpecifier<?>... orders);

    E findFirst(BooleanExpression condition, IncludeColumns includeColumns, GroupBy groupBy,
                  OrderSpecifier<?>... orders);

    E findFirst(BooleanExpression condition, ExcludeColumns excludeColumns, OrderSpecifier<?>... orders);

    E findFirst(BooleanExpression condition, ExcludeColumns excludeColumns, GroupBy groupBy,
                  OrderSpecifier<?>... orders);

    boolean exist();

    boolean exist(BooleanExpression condition);

    boolean notExist();

    boolean notExist(BooleanExpression condition);

    boolean existByPk(ID pk);

    boolean notExistByPk(ID pk);

    long count();

    long count(BooleanExpression condition);

    long insert(E entity);

    long insertBatch(List<E> list);

    /**
     * 创建一个update执行器
     *
     * @return
     */
    UpdateExecuter<E, ID> update();

    UpdateExecuter<E, ID> update(BooleanExpression where);

    UpdateExecuter<E, ID> update(ID pk);

    long update(BooleanExpression condition, E entity, Path<?>... updatePaths);

    long update(BooleanExpression condition, E entity, IncludeColumns includeColumns);

    long update(BooleanExpression condition, E entity, ExcludeColumns excludeColumns);

    boolean updateByPk(ID pk, E entity);

    boolean updateByPk(ID pk, E entity, Path<?>... updatePaths);

    boolean updateByPk(ID pk, E entity, IncludeColumns includeColumns);

    boolean updateByPk(ID pk, E entity, ExcludeColumns excludeColumns);

    boolean updateOne(BooleanExpression condition, E entity, Path<?>... updatePaths);

    boolean updateOne(BooleanExpression condition, E entity, IncludeColumns includeColumns);

    boolean updateOne(BooleanExpression condition, E entity, ExcludeColumns excludeColumns);

    long updateAll(E entity, Path<?>... updatePaths);

    long updateAll(E entity, IncludeColumns includeColumns);

    long updateAll(E entity, ExcludeColumns excludeColumns);

    boolean deleteByPk(ID pk);

    boolean deleteOne(BooleanExpression condition);

    long delete(BooleanExpression condition);

    /**
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     */
    interface SelectExecuter<E, ID> {

        SelectExecuter<E, ID> where(BooleanExpression where);

        SelectExecuter<E, ID> where(ID pk);

        SelectExecuter<E, ID> orderBy(OrderSpecifier<?>... orders);

        SelectExecuter<E, ID> groupBy(Path<?>... columns);

        SelectExecuter<E, ID> having(Predicate... havings);

        SelectExecuter<E, ID> paging(long offset, long limit);

        SelectExecuter<E, ID> offset(long offset);

        SelectExecuter<E, ID> limit(long limit);

        List<E> fetch();

        E fetchFirst();

        E fetchOne();
    }

    /**
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     */
    interface UpdateExecuter<E, ID> {

        UpdateExecuter<E, ID> where(BooleanExpression where);

        UpdateExecuter<E, ID> where(ID pk);

        UpdateEntityExecuter<E, ID> set(E entity);

        <T> UpdateValueExecuter<E, ID> set(Path<T> column, T value);

        <T> UpdateValueExecuter<E, ID> set(Path<T> column, Expression<? extends T> expression);

        <T> UpdateValueExecuter<E, ID> setNull(Path<T> column);

    }

    /**
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     */
    interface UpdateEntityExecuter<E, ID> {

        UpdateEntityExecuter<E, ID> where(BooleanExpression where);

        UpdateEntityExecuter<E, ID> where(ID pk);

        UpdateEntityExecuter<E, ID> include(Path<?>... columns);

        UpdateEntityExecuter<E, ID> exclude(Path<?>... columns);

        long execute();

        boolean executeOne();

    }

    /**
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     */
    interface UpdateValueExecuter<E, ID> {

        UpdateValueExecuter<E, ID> where(BooleanExpression where);

        UpdateValueExecuter<E, ID> where(ID pk);

        <T> UpdateValueExecuter<E, ID> set(Path<T> column, T value);

        <T> UpdateValueExecuter<E, ID> set(Path<T> column, Expression<? extends T> expression);

        <T> UpdateValueExecuter<E, ID> setNull(Path<T> column);

        long execute();

        boolean executeOne();
    }

}
